package com.mask.im.business.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mask.im.business.annotation.AesCrypto;
import com.mask.im.business.annotation.OptLog;
import com.mask.im.business.common.model.RestResponse;
import com.mask.im.business.model.dto.IdentityVFDTO;
import com.mask.im.business.common.model.PageResult;
import com.mask.im.business.model.dto.SliderLocationDTO;
import com.mask.im.business.model.dto.UserAdminDTO;
import com.mask.im.business.model.dto.UserLoginDTO;
import com.mask.im.business.model.entity.UserInfo;
import com.mask.im.business.model.vo.*;
import com.mask.im.business.service.UserAuthService;
import com.mask.im.business.service.UserInfoService;
import com.mask.im.business.strategy.impl.context.RegisterStrategyContext;
import com.mask.im.business.strategy.impl.context.SendCodeStrategyContext;
import com.mask.token.model.MaskUserDetails;
import com.mask.token.service.MaskTokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.mask.im.business.common.constant.OptTypeConstant.UPDATE;

@SuppressWarnings("all")
@Api(tags = "用户账户信息模块")
@Log4j2
@RestController
public class UserAuthController {

    private static final String KEY = "jiamimiyao"; //自定义加密秘钥

    private static final String AES = "AES";    //加密类型

    private static final String AUTHORITY = "Authorization"; //固定头部获取的token的key值


    @Autowired
    private SendCodeStrategyContext sendCodeStrategy;

    @Autowired
    private RegisterStrategyContext registerStrategy;

    @Autowired
    private UserAuthService userAuthService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private MaskTokenService tokenService;

    @Resource
    private UserInfoService userInfoService;

    /**
     * 登录接口
     * 用户需要根据自己的业务逻辑实现
     */
    @PostMapping("/login")
    public RestResponse<Map<String, Object>> login(@RequestBody UserLoginDTO request) {
        try {
            //验证用户凭据（这里需要根据实际业务逻辑实现）
            UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());

//            if (!passwordEncoder.matches(request.getPassword(), userDetails.getPassword())) {
//                return RestResponse.fail(401, "用户名或密码错误");
//            }
            //转换为MaskUserDetails
            MaskUserDetails maskUserDetails = (MaskUserDetails) userDetails;
            maskUserDetails.setDeviceId(request.getDeviceId());
            //生成Token
            String accessToken = tokenService.generateAccessToken(maskUserDetails);
            String refreshToken = tokenService.generateRefreshToken(maskUserDetails);
            UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getId, maskUserDetails.getUserId()));

            //返回结果
            Map<String, Object> data = new HashMap<>();
            data.put("accessToken", accessToken);
            data.put("refreshToken", refreshToken);
            data.put("userInfo", userInfo);
            data.put("tokenType", "Bearer");
            data.put("expiresIn", 7200);
            return RestResponse.ok(data);
        } catch (Exception e) {
            log.error("登录出错" + e.getMessage(), e);
            return RestResponse.fail(401, "用户名或密码错误");
        }
    }

    @ApiOperation(value = "发送验证码", notes = "用于用户登入注册获取验证码", httpMethod = "GET")
    @GetMapping("/users/userAuth/sendCode/{type}")
    public RestResponse<String> sendCode(
            @PathVariable("type") String type,
            @RequestParam(value = "account", defaultValue = "") String account) {
        sendCodeStrategy.executeStrategySendCode(type, account);
        return RestResponse.ok();
    }

    @ApiOperation(value = "用户注册", notes = "可根据邮箱或手机号注册", httpMethod = "POST")
    @PostMapping("/users/userAuth/register/{type}")
    @AesCrypto
    public RestResponse<String> register(
            @PathVariable String type,
            @Valid @RequestBody RegisterVO registerVO) {
        registerStrategy.executeStrategyRegister(type, registerVO);
        return RestResponse.ok();
    }

    @ApiOperation(value = "手机验证码登入", notes = "手机验证码登入", httpMethod = "POST")
    @PostMapping("/users/userAuth/verificationLogin/phone")
    @AesCrypto
    public RestResponse<?> verificationLogin(@RequestBody PhoneLoginVO phoneLoginVO) {
        return userAuthService.phoneLogin(phoneLoginVO);
    }

    @ApiOperation(value = "退出账号", notes = "退出账号", httpMethod = "POST")
    @PostMapping("/userAuth/logout")
    @AesCrypto
    public RestResponse<?> logout() {
        userAuthService.logout();
        return RestResponse.ok();
    }

    @ApiOperation(value = "查询后台用户列表")
    @GetMapping("/admin/users")
    public RestResponse<PageResult<UserAdminDTO>> listUsers(ConditionVO conditionVO) {
        return RestResponse.ok(userAuthService.listUsers(conditionVO));
    }

    @OptLog(optType = UPDATE)
    @ApiOperation(value = "用户修改密码", notes = "输入旧密码来修改为最新密码")
    @PostMapping("/users/update/password")
    @AesCrypto
    public RestResponse<?> updateUsersPassword(@Valid @RequestBody PasswordVO passwordVO) {
        userAuthService.updateAdminPassword(passwordVO);
        return RestResponse.ok();
    }

    @OptLog(optType = UPDATE)
    @ApiOperation(value = "管理员修改密码", notes = "输入旧密码来修改为最新密码")
    @PostMapping("/admin/update/password")
    public RestResponse<?> updateAdminPassword(@Valid @RequestBody PasswordVO passwordVO) {
        userAuthService.updateAdminPassword(passwordVO);
        return RestResponse.ok();
    }

    @ApiOperation(value = "gitee回调", notes = "gitee回调")
    @RequestMapping("/gitee/callback")
    public RestResponse<?> giteeLogin(@RequestParam("accessToken") String accessToken) {
        return userAuthService.giteeLogin(accessToken);

    }

    @ApiOperation(value = "github回调", notes = "github回调")
    @RequestMapping("/github/callback")
    public RestResponse<?> gitHubLogin(@RequestParam("accessToken") String accessToken) {
        return userAuthService.gitHubLogin(accessToken);
    }

    @ApiOperation(value = "qq回调", notes = "github回调")
    @RequestMapping("/qq/callback")
    public RestResponse<?> QQLogin(@RequestParam("accessToken") String accessToken) {
        return userAuthService.QQLogin(accessToken);
    }


    @ApiOperation(value = "获取登入账户", notes = "获取登入账户")
    @GetMapping("/users/getLoginAccount")
    public RestResponse<IdentityVFDTO> getLoginAccount(@RequestParam("loginAccount") String loginAccount) {
        return userAuthService.getLoginAccount(loginAccount);
    }


    @ApiOperation("邮箱或手机校验")
    @PostMapping("/users/authentication/{type}")
    @AesCrypto
    public RestResponse<String> authentication(@PathVariable String type,
                                               @RequestBody @Valid IdentityVerificationVO verificationVO) {
        return userAuthService.authentication(type, verificationVO);
    }


    @ApiOperation("查找账号")
    @PostMapping("/users/find/account/{type}")
    @AesCrypto
    public RestResponse<List<String>> findAccount(@PathVariable String type,
                                                  @RequestBody @Valid IdentityVerificationVO verificationVO) {
        List<String> account = userAuthService.findAccount(type, verificationVO);
        return RestResponse.ok(account);
    }

    @ApiOperation("更新邮箱或手机号")
    @PostMapping("/users/update/EmailOrPhone")
    @AesCrypto
    public RestResponse<String> updateEmailOrPhone(@RequestBody UpdateEmailOrPhoneVO updateEmailOrPhoneVO) {
        userAuthService.updateEmailOrPhone(updateEmailOrPhoneVO);
        return RestResponse.ok();
    }

    @ApiOperation(value = "更新密码", notes = "用于忘记密码时修改")
    @PostMapping("/users/forgot/updatePassword")
    @AesCrypto
    public RestResponse<String> forgotPasswordUpdate(@RequestBody UpdatePasswordVO updatePasswordVO) {
        return userAuthService.forgotPasswordUpdate(updatePasswordVO);
    }

    @ApiOperation(value = "获取用户账户id", notes = "获取用户账户id")
    @GetMapping("/users/getUserAuthId")
    public RestResponse<?> getUserAuthId(@RequestParam("id") String id) {
        return userAuthService.getUserAuthId(id);
    }

    @ApiOperation(value = "第三方获取token", notes = "第三方获取token")
    @GetMapping("/users/{type}/getAccessToken")
    public RestResponse<String> getAccessToken(@PathVariable String type,
                                               @RequestParam("code") String code) {
        return userAuthService.getAccessToken(type, code);
    }

    @ApiOperation(value = "发送短信验证码身份识别标志", notes = "发送短信验证码身份识别标志")
    @GetMapping("/users/getSliderFlag/{type}")
    public RestResponse<String> getSliderFlag(@PathVariable Integer type) {
        return userAuthService.getSliderFlag(type);
    }

    @ApiOperation("获取校验位置")
    @GetMapping("/sliderlocation")
    public RestResponse<SliderLocationDTO> getSliderLocation(@RequestParam("type") String type) {
        return userAuthService.getSliderLocation(type);
    }

    @ApiOperation("用户检验滑块位置正确性")
    @PostMapping("/users/verifysliderlocation")
    @AesCrypto
    public RestResponse<SliderLocationDTO> userVerifySliderLocation(@RequestBody VerifySliderLocationVO verifySliderLocationVO) {
        return userAuthService.verifySliderLocation(verifySliderLocationVO);
    }

    @ApiOperation("管理员检验滑块位置正确性")
    @PostMapping("/admin/verifysliderlocation")
    public RestResponse<SliderLocationDTO> adminVerifySliderLocation(@RequestBody VerifySliderLocationVO verifySliderLocationVO) {
        return userAuthService.verifySliderLocation(verifySliderLocationVO);
    }
}
